#ifndef  HELPER_OBJECTPTR_H
#define  HELPER_ OBJECTPTR_H

#include <functional>
namespace helper {

template<typename T>
class BaseObjectPtr {
public:
  template<typename V>
  BaseObjectPtr(V * ptr) 
  :_ptr(ptr) 
  {
  }
  virtual ~BaseObjectPtr(){
  }

  inline T & operator *() {
    return *_ptr;
  }
  inline T * operator ->(){
    return _ptr;
  }
  inline T * get() const {
    return _ptr;
  }
  inline bool empty() const {
    return _ptr == nullptr;
  }

  inline void reset(){
    _ptr = nullptr;
  }
  template<typename V>
  inline void reset(V * v) {
    _ptr = v;
  }

private:
  T * _ptr;
};

template<typename T>
class IPinnable {
public:
  IPinnable(bool bPin = true) 
  : _bPin(bPin) 
  {
  }

  virtual ~IPinnable(){
  }

  virtual T * pin() = 0;
  virtual void eject()  = 0;

  inline bool isPin() const {
    return _bPin;
  }
  inline void setPin(bool bPin){
    this->_bPin = bPin;
  }
private:
  bool _bPin;
};

template<typename T>
class PinnableObjectPtr : public BaseObjectPtr<T> , public IPinnable<T> {
public:
  template<typename V>
  PinnableObjectPtr(V * obj, bool bPin = false)
  : BaseObjectPtr<T>(obj)
  , IPinnable<T>(bPin)
  {
  }

  ~PinnableObjectPtr()override {
  }

  T * pin() override {
    this->setPin(true);
    return this->get();
  }
  void eject() override {
    //not-support
  }
};


} // end of namespace helper


#endif   /* HELPER_OBJECTPTR_H */
